/*

opt.c - Parse options list as passed to a program

*/

/*...sincludes:0:*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#define	OPT_C
#include "opt.h"
/*...e*/

/*...svars:0:*/
#define	ONECASE	('z'+1-'a')
#define	LETTERS	(ONECASE+ONECASE)

static struct
	{
	BOOLEAN	got;
	const char *text;
	} opt_t [LETTERS];

#define	INDEX(c) ((c)<='Z'?(c)-'A':(c)-'a'+ONECASE)

static BOOLEAN hyphen = FALSE;
/*...e*/
/*...sproc_opt:0:*/
/*...sproc_noargs:0:*/
static BOOLEAN proc_noargs(const char *arg, const char *noarg_opts)
	{
	int c;
	const char *s;

	s = arg + 1;
	if ( *s )
		{
		while ( (c = *s) != '\0' && c != '=' && strchr(noarg_opts, c) != NULL )
			{
			opt_t[INDEX(c)].got = TRUE;
			++s;
/*			strcpy(s, s + 1);	*/
			}
		return !*s;
		}
	else if ( strchr(noarg_opts, '-') != NULL )
		{
		hyphen = TRUE;
		return TRUE;
		}
	return FALSE;
	}
/*...e*/

#define	USEARG	argv2++;*argc-=1

BOOLEAN	proc_opt(
	int *argc, char *argv [],
	const char *noarg_opts, const char *arg_opts
	)
			/* return FALSE if invalid options found in argv   */
	{
	BOOLEAN	only_valid = TRUE;
	int c, i, inx;
	char **argv2;			/* not char *argv2[] see K&R p94 */

	for ( i = 0; i < LETTERS; i++)
		{
		opt_t[i].got  = FALSE;
		opt_t[i].text = NULL;
		}
	i = *argc;
	argv2 = ++argv;
	while ( i-- > 1 )
		{
		if ( **argv2 == '-' )	/* option */
			{
			c = argv2[0][1];
			if ( c == '-' )
				/* Found --, meaning stop scanning for opts */
				{
				USEARG;
				while ( i-- > 1 )
					*argv++ = *argv2++;
				return only_valid;
				}
			else if ( proc_noargs(*argv2, noarg_opts) )
				{
				USEARG;
				}
			else
				{
				inx = INDEX(c);
				if ( strchr(arg_opts, c) != NULL )
					{
					opt_t[inx].got = TRUE;
					USEARG;
					if ( i > 1 )
						{
						opt_t[inx].text = *argv2;
						USEARG;
						i--;
						}
					else
						opt_t[inx].text = NULL;
					}
				else
					{
					only_valid = FALSE;
					*argv++ = *argv2++;
					}
				}
			}

		else
			*argv++ = *argv2++;
		}
	return only_valid;
	}
/*...e*/
/*...sopt:0:*/
BOOLEAN	opt(const char *s, const char **sp)
	{
	int inx;

	if ( *s == '-' )
		return hyphen;
	inx = INDEX(*s);
	if ( *++s )			/* want argument too */
		*sp = opt_t[inx].text;
	return opt_t [inx].got;
	}
/*...e*/
